package com.ncr.travel.appmgr.client.view;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.xml.client.DOMException;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;
import com.google.inject.Inject;
import com.ncr.travel.appmgr.client.ConfigResources;
import com.ncr.travel.appmgr.client.ConfigurationItem;
import com.ncr.travel.appmgr.client.model.ScreenConfigurationFactory;
import com.ncr.travel.appmgr.client.mvp.EventBus;
import com.ncr.travel.appmgr.client.presenter.FunctionPresenter;
import com.ncr.travel.appmgr.model.shared.AuditField;
import com.ncr.travel.appmgr.model.shared.Function;
import com.ncr.travel.appmgr.model.shared.ScreenConfiguration;
import com.ncr.travel.appmgr.model.shared.StationsAuditCriteria;
import com.ncr.travel.appmgr.style.client.AppManagerStyleClientBundle;

public class FunctionWidget extends Composite implements FunctionView, HasText {

	private static FunctionAppMgrWindowUiBinder uiBinder = GWT.create(FunctionAppMgrWindowUiBinder.class);

	@UiTemplate("FunctionView.ui.xml")
	interface FunctionAppMgrWindowUiBinder extends UiBinder<Widget, FunctionWidget> {
	}
    /**
     * Factory for screen config model objects.
     */
	private ScreenConfigurationFactory screenConfigurationFactory;

	private final HashMap<Integer, Function> mapUpdatedList = new HashMap<Integer, Function>();

	private ConfigEditorView configEditor;

	private FunctionPresenter presenter;

	@UiField
	ScrollPanel functionScrollPanel;
	@UiField
	VerticalPanel vPanel;
	@UiField
	HTMLPanel htmlPanel;
	private ScreenConfiguration screenConfiguration;

	/**
	 * Constructor
	 */
	@Inject
	public FunctionWidget(ScreenConfigurationFactory screenConfigurationFactory, EventBus eventBus) {
		initWidget(uiBinder.createAndBindUi(this));
		System.out.println("Constructing FunctionWidget");
		this.screenConfigurationFactory = screenConfigurationFactory;
		this.configEditor = new ConfigEditorWidget(
				"Are you sure you want to confirm functions configuration changes?", eventBus);
		configEditor.setConfigurationItem(ConfigurationItem.FUNCTION);
		htmlPanel.add(configEditor.asWidget());

		Label spacing = new Label();
		spacing.setSize("100", "50");
		vPanel.add(spacing);
		vPanel.setStyleName("verticalSplitPanel");
		vPanel.setSize("100%", "100%");
	}

	@Override
	public void setScreenConfiguration(final ScreenConfiguration screenConfiguration) {
		this.screenConfiguration = screenConfiguration;
		configEditor.setScreenConfiguration(screenConfiguration);
	}

	@Override
	public String getText() {
		return null;
	}

	@Override
	public void setText(String text) {

	}

	@Override
	public HasWidgets getHtmlPanel() {
		return htmlPanel;
	}

	@Override
	public ConfigEditorView getConfigEditor() {
		return configEditor;
	}

	@Override
	public ScrollPanel getFunctionScrollPanel() {
		return functionScrollPanel;
	}

	@Override
	public VerticalPanel getVerticalPanel() {
		return vPanel;
	}

	@Override
	public void setPresenter(FunctionPresenter presenter) {
		this.presenter = presenter;
	}

	@Override
	public void showView() {
		String screenData = ConfigResources.INSTANCE.initialConfiguration().getText();
		System.out.println("(FunctionWidget) Called showView()");
		vPanel.clear();
		configEditor.disableAllControls();
		List<Function> functions = screenConfiguration.getFunctions();
		final AppManagerStyleClientBundle imgResources = GWT.create(AppManagerStyleClientBundle.class);
		if (functions != null && functions.size() > 0) {

			HashMap<String, FunctionControls> functionControls = createFunctionControls(functions, screenData);

			for (int index = 0; index < functions.size(); index++) {	
				final ListBox lb = new ListBox();
				Function fData = functions.get(index);
				Function updateFuncData = screenConfigurationFactory.function().as();
				Function originalFuncData = screenConfigurationFactory.function().as();

				final ArrayList<String> al = new ArrayList<String>();
				al.add("0");
				final Button onButton = new Button();
				final Button offButton = new Button();

				Image buttonImg = new Image(imgResources.onButtonImage());

				ClickHandler buttonclickhandler = new ClickHandler() {
					public void onClick(ClickEvent event) {

						Image buttonValue = (Image) event.getSource();

						HorizontalPanel panel = (HorizontalPanel) buttonValue.getParent();
						Widget radioButton = panel.getWidget(1);
						Widget selectBox = panel.getWidget(panel.getWidgetCount() - 2);
						boolean allStations = false;
						if (radioButton instanceof RadioButton) {
							allStations = ((RadioButton) radioButton).getValue();
						}

						Integer selectId = null;
						if (selectBox instanceof ListBox) {
							selectId = ((ListBox) selectBox).getSelectedIndex();
						}
						
						String functionId = buttonValue.getElement().getId().substring(5);
						Integer id = Integer.parseInt(functionId);
						Function modifiedData = mapUpdatedList.get(id);

						StationsAuditCriteria criteria = modifiedData.getAuditCriteria();
						//update image.
						
						if (buttonValue.getAltText().equals("ON")) {
							buttonValue.setResource(imgResources.offButtonImage());
							buttonValue.setAltText("OFF");
						} else if (buttonValue.getAltText().equals("OFF")) {
							buttonValue.setResource(imgResources.onButtonImage());
							buttonValue.setAltText("ON");
						}
						//update value.
						if (criteria != null && criteria.getStations() != null) {
							List<AuditField> criterias = criteria.getStations();
							if (criterias.size() != 0) {
								if (allStations) {
									criteria.setAllStations(true);
									//all stations updated.
									for (AuditField field : criterias) {
										field.setAvailable(buttonValue.getAltText().equals("ON"));
									}
								} else if (selectId != null && selectId != 0) {
									//only one station.
									criteria.setAllStations(false);
									criterias.get(selectId - 1).setAvailable(buttonValue.getAltText().equals("ON"));
								}
							}
							criteria.setStations(criterias);
							//System.out.println(criteria.getStations().get(selectId - 1).isAvailable());
						}
						modifiedData.setAuditCriteria(criteria);
						//System.out.println(modifiedData.getAuditCriteria().getStations().get(selectId - 1).isAvailable());
						mapUpdatedList.put(modifiedData.getId(), modifiedData);
					}
				};
				buttonImg.addClickHandler(buttonclickhandler);

				Integer functionId = fData.getId();
				String functionName = fData.getName();
				System.out.println("Adding function id = '" + functionId + "'");
				System.out.println("and function name = '" + functionName + "'");

				boolean active = fData.isActive();
				StationsAuditCriteria functionStationAuditCriteria = fData.getAuditCriteria();

				final StationsAuditCriteria updateFuncStationAuditCriteria =
					screenConfigurationFactory.stationsAuditCriteria().as();
				List<AuditField> stationList = null;
				boolean allStations = false;

				if (functionStationAuditCriteria != null) {
					stationList = functionStationAuditCriteria.getStations();
					allStations = functionStationAuditCriteria.isAllStations();

					updateFuncStationAuditCriteria.setAllStations(allStations);
					updateFuncStationAuditCriteria.setStations(stationList);
				}

				buttonImg.getElement().setId("ONOFF" + functionId);
				buttonImg.setAltText(fData.isActive() ? "ON" : "OFF");

				updateFuncData.setAuditCriteria(functionStationAuditCriteria);
				updateFuncData.setActive(fData.isActive());
				updateFuncData.setId(functionId);
				updateFuncData.setName(functionName);

				originalFuncData.setId(functionId);
				originalFuncData.setName(functionName);
				originalFuncData.setActive(fData.isActive());

				if (active == true) {
					onButton.setStyleName("onButton");
					offButton.setStyleName("offButton");
				} else {
					onButton.setStyleName("offButton");
					offButton.setStyleName("onButton");
				}

				FunctionControls functionCtrls = functionControls.get(functionName);
				String isSelectEnabled = functionCtrls.isSelectEnabled();
				String isRadioEnabled = functionCtrls.isRadioEnabled();

				Label label3 = new Label();
				label3.setText(functionName);
				label3.setStyleName("confLabelHeader");

				HorizontalPanel hPanel = new HorizontalPanel();
				hPanel.setSize("100%", "100%");
				hPanel.add(label3);
				hPanel.setSpacing(10);

				// HorizontalPanel horizontalPanel = new HorizontalPanel();
				// view.getVerticalPanel().add(horizontalPanel);

				final RadioButton functionRadioButton = new RadioButton("allStationsRadio", "ALL STATIONS");

				if (isRadioEnabled.equals("true")) {
					functionRadioButton.setValue(allStations);
					hPanel.add(functionRadioButton);
				} else {
					HorizontalPanel blankPanel = new HorizontalPanel();
					blankPanel.setWidth("111px");
					hPanel.add(blankPanel);
				}
				if (isSelectEnabled.equals("true")) {
					// final ListBox lb = new ListBox();
					lb.addStyleName("selectStations");
					lb.addItem("Station");

					List<AuditField> updateStationList;

					if (stationList.size() > 0) {
						Iterator<AuditField> itr1 = stationList.iterator();

						updateStationList = new ArrayList<AuditField>();
						while (itr1.hasNext()) {

							AuditField functionStationData = itr1.next();
							AuditField updateFunctionStationData = screenConfigurationFactory.auditField().as();
							String station = functionStationData.getStation();

							updateFunctionStationData.setStation(station);
							updateFunctionStationData.setAvailable(functionStationData.isAvailable());
							updateStationList.add(updateFunctionStationData);
							lb.addItem(station);

						}
						updateFuncStationAuditCriteria.setStations(updateStationList);
						updateFuncStationAuditCriteria.setAllStations(allStations);
					}

					updateFuncData.setAuditCriteria(updateFuncStationAuditCriteria);
					// ArrayList seletecIndexList = new ArrayList();

					lb.addChangeHandler(new ChangeHandler() {

						public void onChange(ChangeEvent event) {
							getConfigEditor().enablePreviewControl();
							updateFuncStationAuditCriteria.setAllStations(false);

							ListBox listBox = (ListBox) event.getSource();
							
							HorizontalPanel panel = (HorizontalPanel) listBox.getParent();
							Image buttonImg = (Image) panel.getWidget(panel.getWidgetCount() - 1);
							Widget radioButton = panel.getWidget(1);
							Integer functionId = Integer.parseInt(buttonImg.getElement().getId().substring(5));
							Function current = mapUpdatedList.get(functionId);
							if (radioButton instanceof RadioButton) {
								((RadioButton) radioButton).setValue(false);
							}
							if (lb.getSelectedIndex() != 0) {
								if (current.getAuditCriteria().getStations().get(lb.getSelectedIndex() - 1).isAvailable()) {
									buttonImg.setAltText("ON");
									buttonImg.setResource(imgResources.onButtonImage());
								} else {
									buttonImg.setAltText("OFF");
									buttonImg.setResource(imgResources.offButtonImage());
								}
							}
						}
					});

					hPanel.add(lb);
					// isSelected
				} else {
					HorizontalPanel blankPanel = new HorizontalPanel();
					blankPanel.setWidth("117px");
					hPanel.add(blankPanel);
				}

				// for the first time this will come here, onclick of every
				// time this will go into onclick loops only
				// updateFuncData.setActive(active);
				mapUpdatedList.put(updateFuncData.getId(), updateFuncData);

				this.screenConfiguration.setFunctions(new ArrayList<Function>(mapUpdatedList.values()));

				hPanel.add(buttonImg);
				hPanel.setCellHorizontalAlignment(buttonImg, HasHorizontalAlignment.ALIGN_RIGHT);

				getVerticalPanel().add(hPanel);

				getVerticalPanel().add(new HTML("<hr>"));

			}// while
		}// list if end
	}

	private HashMap<String, FunctionControls> createFunctionControls(
			List<Function> functions, String screenData) throws DOMException {

		List<String> functionNames = new ArrayList<String>();
		for (int j = 0; j < functions.size(); j++) {
			Function function = functions.get(j);
			if (function != null) {
				functionNames.add(function.getName());
				//add to list
				mapUpdatedList.put(j, function);
			}
		}

		HashMap<String, FunctionControls> functionControls = new HashMap<String, FunctionControls>();
		Document messageDoc = XMLParser.parse(screenData);
		NodeList functionList = messageDoc.getElementsByTagName("Function");

		for (int i = 0; i < functionList.getLength(); i++) {

			Node node = functionList.item(i);
			Element function = (Element) node;
			// After the above step error 2 times iterating
			Node nodeVal = function.getElementsByTagName("Name").item(0);

			if (functionNames.contains(nodeVal.getFirstChild().getNodeValue())) {

				NodeList nList = function.getElementsByTagName("RadioButton");
				String isRadioButtonRequired = nList.item(0).getFirstChild().getNodeValue();

				NodeList nList1 = function.getElementsByTagName("SelectBox");
				String isSelectBoxRequired = nList1.item(0).getFirstChild().getNodeValue();
				functionControls.put(nodeVal.getFirstChild().getNodeValue(), new FunctionControls(
						isRadioButtonRequired, isSelectBoxRequired));
			}
		}
		return functionControls;
	}

	private static class FunctionControls {

		private final String isRadioEnabled;
		private final String isSelectEnabled;

		public FunctionControls(String isRadioEnabled, String isSelectEnabled) {
			super();
			this.isRadioEnabled = isRadioEnabled;
			this.isSelectEnabled = isSelectEnabled;
		}

		public String isRadioEnabled() {
			return isRadioEnabled;
		}

		public String isSelectEnabled() {
			return isSelectEnabled;
		}

	}
}